sha256.js ➔ sha256Block   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 26
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 22
dl 0
loc 26
ccs 20
cts 20
cp 1
crap 4
rs 9.352
c 0
b 0
f 0
1
/**
2
 * @license
3
 * Copyright (c) 2020 UMI
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
6
 * of this software and associated documentation files (the "Software"), to deal
7
 * in the Software without restriction, including without limitation the rights
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included in all
13
 * copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 * SOFTWARE.
22
 */
23
24
'use strict'
25
26 1
const sha256K = [
27
  0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
28
  0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
29
  0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
30
  0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
31
  0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
32
  0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
33
  0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
34
  0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
35
]
36
/**
37
 * Безопасный алгоритм хеширования, SHA2-256.
38
 * @see https://en.wikipedia.org/wiki/SHA-2
39
 * @param {ArrayLike<number>} message message
40
 * @returns {number[]} hash
41
 * @private
42
 */
43
function sha256 (message) {
44 4
  const h = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19]
45 4
  const chunks = sha256PreProcess(message)
46 4
  for (let j = 0, l = chunks.length; j < l; j++) {
47 6
    const w = chunks[j]
48 6
    for (let i = 16; i < 64; i++) {
49 288
      const s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >>> 3)
50 288
      const s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >>> 10)
51 288
      w[i] = w[i - 16] + s0 + w[i - 7] + s1
52
    }
53 6
    sha256Block(h, w)
54
  }
55 4
  const digest = []
56 4
  for (let i = 0; i < 8; i++) {
57 32
    digest[digest.length] = h[i] >>> 24 & 0xff
58 32
    digest[digest.length] = h[i] >>> 16 & 0xff
59 32
    digest[digest.length] = h[i] >>> 8 & 0xff
60 32
    digest[digest.length] = h[i] & 0xff
61
  }
62 4
  return digest
63
}
64
/**
65
 * @param {ArrayLike<number>} message
66
 * @returns {number[][]}
67
 * @private
68
 */
69
function sha256PreProcess (message) {
70 4
  const bytez = []
71
  let i
72
  let l
73 4
  for (i = 0, l = message.length + 8 + (64 - ((message.length + 8) % 64)); i < l; i++) {
74 384
    bytez[i] = message[i] || 0
75
  }
76 4
  bytez[message.length] = 0x80
77 4
  bytez[bytez.length - 2] = ((message.length * 8) >>> 8) & 0xff
78 4
  bytez[bytez.length - 1] = (message.length * 8) & 0xff
79 4
  const chunks = []
80 4
  for (i = 0, l = bytez.length; i < l; i += 64) {
81 6
    const chunk = []
82 6
    for (let j = 0; j < 64; j += 4) {
83 96
      let n = i + j
84 96
      chunk[chunk.length] = (bytez[n] << 24) + (bytez[++n] << 16) + (bytez[++n] << 8) + bytez[++n]
85
    }
86 6
    chunks[chunks.length] = chunk
87
  }
88 4
  return chunks
89
}
90
/**
91
 * @param {number[]} h
92
 * @param {number[]} w
93
 * @private
94
 */
95
function sha256Block (h, w) {
96 6
  const a = []
97
  let i
98 6
  for (i = 0; i < 8; i++) {
99 48
    a[i] = h[i]
100
  }
101 6
  for (i = 0; i < 64; i++) {
102 384
    const S1 = rotr(a[4], 6) ^ rotr(a[4], 11) ^ rotr(a[4], 25)
103 384
    const ch = (a[4] & a[5]) ^ ((~a[4]) & a[6])
104 384
    const t1 = a[7] + S1 + ch + sha256K[i] + w[i]
105 384
    const S0 = rotr(a[0], 2) ^ rotr(a[0], 13) ^ rotr(a[0], 22)
106 384
    const ma = (a[0] & a[1]) ^ (a[0] & a[2]) ^ (a[1] & a[2])
107 384
    const t2 = S0 + ma
108 384
    a[7] = a[6]
109 384
    a[6] = a[5]
110 384
    a[5] = a[4]
111 384
    a[4] = a[3] + t1
112 384
    a[3] = a[2]
113 384
    a[2] = a[1]
114 384
    a[1] = a[0]
115 384
    a[0] = t1 + t2
116
  }
117 6
  for (i = 0; i < 8; i++) {
118 48
    h[i] = h[i] + a[i] | 0
119
  }
120
}
121
/**
122
 * @param {number} n
123
 * @param {number} i
124
 * @returns {number}
125
 * @private
126
 */
127
function rotr (n, i) {
128 3456
  return (n >>> i) | (n << (32 - i))
129
}
130
131
exports.sha256 = sha256
132